//
//  NSMainView.m
//  SpeedTest
//
//  Created by Han Mingjie on 2020/1/2.
//  Copyright © 2020 MingJie Han. All rights reserved.
//

#import "NSECGLinesView.h"
#import "NSPieceView.h"
#import "pthread.h"
#import "NSECGStandardView.h"
#define NO_ECG_LINE_VALUE -50000
@interface NSECGLinesView()<NSPieceViewDataSource>{
    NSMutableArray <NSPieceView *>*views_array;
    NSECGStandardView *standard_view;
    NSUInteger number_for_pieceviews;
    NSUInteger current_pieceview_index;
    NSUInteger erase_before_index;

    NSMutableArray <NSNumber *>*values_array;
    NSUInteger current_values_array_index;
    NSUInteger received_values_times;
    NSUInteger showed_values_times;
    
    pthread_mutex_t data_mutex;
    
    CGSize view_size;

    float piece_width;                          //Piece宽度
    float x_seek_per_point;                     //每个点右移点数
    int number_for_more_point_side;             //为PieceView多给出的ECG点数
    NSUInteger need_points_per_pieceview;       //每个Piece所需点数量
}

@end
@implementation NSECGLinesView
@synthesize delegate;
@synthesize ecg_name_array;
@synthesize standard_style;
@synthesize style;
@synthesize standard_text_color;
@synthesize standard_text_font;
@synthesize lost_line_color;
@synthesize x_speed,y_rate,pix_per_mm,ECG_rate,view_fresh,space_pix,line_width,line_color;
@synthesize ecg_controller;
@synthesize self_width;

#pragma mark - Value Set Start
-(void)setEcg_name_array:(NSArray<NSString *> *)_ecg_name_array{
    ecg_name_array = _ecg_name_array;
    standard_view.ecg_name_array = ecg_name_array;
    [self init_values_array];
    for (NSPieceView *view in views_array){
        view.ecg_name = ecg_name_array;
    }
}

-(void)setStandard_style:(NSECGRealTimeView_Standard)_standard_style{
    standard_style = _standard_style;
    standard_view.standard_style = standard_style;
    [self init_values_array];
}

-(void)setStyle:(NSECGRealTimeView_Style)_style{
    style = _style;
    standard_view.style = style;
    [self init_values_array];
}

-(void)setX_speed:(float)_x_speed{
    x_speed = _x_speed;
    [self init_values_array];
}

-(void)setY_rate:(float)_y_value{
    y_rate = _y_value;
    standard_view.y_rate = y_rate;
    [self init_values_array];
}

-(void)setECG_rate:(float)_ECG_rate{
    ECG_rate = _ECG_rate;
    [self init_values_array];
}

-(void)setView_fresh:(float)_view_fresh{
    view_fresh = _view_fresh;
    [self init_values_array];
}

-(void)setPix_per_mm:(float)_mm_per_pix{
    pix_per_mm = _mm_per_pix;
    standard_view.pix_per_mm = pix_per_mm;
    [self init_values_array];
}

-(void)setSpace_pix:(NSUInteger)_space_pix{
    space_pix = _space_pix;
    [self init_values_array];
}

-(void)setStandard_text_font:(UIFont *)_standard_text_font{
    standard_text_font = _standard_text_font;
    standard_view.standard_text_font = standard_text_font;
}

-(void)setLine_color:(UIColor *)_line_color{
    line_color = _line_color;
    standard_view.line_color = line_color;
    for (NSPieceView *view in views_array){
        view.line_color = line_color;
    }
}

-(void)setLost_line_color:(UIColor *)_lost_line_color{
    lost_line_color = _lost_line_color;
    for (NSPieceView *view in views_array){
        view.lost_line_color = lost_line_color;
    }
}

-(void)setStandard_text_color:(UIColor *)_standard_text_color{
    standard_text_color = _standard_text_color;
    standard_view.standard_text_color = standard_text_color;
}
        
-(void)setLine_width:(float)_line_width{
    line_width = _line_width;
    standard_view.line_width = line_width;
    for (NSPieceView *view in views_array){
        view.line_width = line_width;
    }
}


#pragma mark - Value Set End


-(float)middleFor:(NSString *)lead_name{
    float per_line_height = view_size.height/(ecg_name_array.count+1);
    NSUInteger index = [ecg_name_array indexOfObject:lead_name] + 1;
#if TARGET_OS_IOS
    return index * per_line_height;
#else
    return view_size.height - index * per_line_height;
#endif
}


#pragma mark - NSPieceViewDataSource Start
-(NSArray <NSArray <NSNumber *>*>*)getValueFrom:(NSPieceView *)pieceView{
    if (pieceView.index ==  current_pieceview_index + erase_before_index){
        return nil;
    }
    NSMutableArray *result_array = [[NSMutableArray alloc] init];
    NSMutableArray *lead_status_array = [[NSMutableArray alloc] init];
    NSUInteger lenght = 2 * number_for_more_point_side + piece_width/x_seek_per_point;
    // 17.84 466
    // 26.3999996 660
    for (NSString *lead_name in pieceView.ecg_name){
        BOOL lead_connected;
        NSMutableArray <NSNumber *>* res = [ecg_controller getValueForLead:lead_name lenght:lenght status:&lead_connected withDataIndex:pieceView.data_index];
        [lead_status_array addObject:[NSNumber numberWithBool:lead_connected]];
        float middle = [self middleFor:lead_name];
        for (int i=0;i<res.count;i++){
            float value = [[res objectAtIndex:i] floatValue];
            value = y_rate * value * pix_per_mm / 1000.f;
    #if TARGET_OS_IOS
            [res replaceObjectAtIndex:i withObject:[NSNumber numberWithFloat:middle - value]];
    #else
            [res replaceObjectAtIndex:i withObject:[NSNumber numberWithFloat:middle + value]];
    #endif
        }
        if (res){
            [result_array addObject:res];
        }
    }
    pieceView.ecg_lead_status = lead_status_array;
    return result_array;
}
#pragma mark - NSPieceViewDataSource End


-(void)fresh_in_threadWithIndex:(NSUInteger)index{
//    NSLog(@"current:%d, in %d", current_pieceview_index, views_array.count);
    if (number_for_pieceviews <= 0){
        return;
    }
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [dict setObject:[NSNumber numberWithInteger:current_pieceview_index] forKey:@"Index"];
    [dict setObject:[NSNumber numberWithInteger:index] forKey:@"Data_Index"];
    __strong __typeof__(self) strongSelf = self;
    [strongSelf performSelector:@selector(fresh_piece_in_thread:) withObject:dict];
    current_pieceview_index ++;
    if (current_pieceview_index >= number_for_pieceviews){
        current_pieceview_index = 0;
    }
    return;
}

-(void)cancelAllRefresh{
    for (NSPieceView *pieceView in views_array){
        pieceView.isDrawNewLine = NO;
    }
}

-(void)fresh_piece_in_thread:(NSDictionary *)dict{
    NSInteger index = [[dict valueForKey:@"Index"] integerValue];
    NSInteger data_index = [[dict valueForKey:@"Data_Index"] integerValue];
    NSUInteger erase_index = index + erase_before_index;
    while (erase_index >= number_for_pieceviews){
        erase_index -= number_for_pieceviews;
    }
    if (erase_index < views_array.count){
        NSPieceView *clean_view = [views_array objectAtIndex:erase_index];
        [clean_view clean_in_thread];
    }

    if (index < views_array.count){
        NSPieceView *fresh_view = [views_array objectAtIndex:index];
        fresh_view.data_index = data_index;
        [fresh_view fresh_in_thread];
    }
}

-(void)change_size{
    CGRect rect;
    piece_width = pix_per_mm * x_speed / view_fresh;
    
    BOOL isLeftRowECG = YES;
    if (self.frame.origin.x > 10.f){
        //不是最左边的ECG 列
        isLeftRowECG = NO;
    }
    
    BOOL needStandardView = NO;
    switch (standard_style) {
        case NSECGRealTimeView_Standard_Hidden:
            needStandardView = NO;
            break;
        case NSECGRealTimeView_Standard_Show:
            needStandardView = YES;
            break;
        case NSECGRealTimeView_Standard_Auto:
            switch (style) {
                case NSECGRealTimeView_Style_6x2:
                    needStandardView = YES;
                    break;
                case NSECGRealTimeView_Style_limb_leads:
                    needStandardView = YES;
                    break;
                case NSECGRealTimeView_Style_12x1:
                    needStandardView = YES;
                    break;
                case NSECGRealTimeView_Style_3x4:
                    if (1 == ecg_name_array.count){
                        needStandardView = YES;
                    }else{
                        needStandardView = NO;
                    }
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
    
    if (needStandardView){
        number_for_pieceviews = ((NSUInteger)self.frame.size.width - 5 * pix_per_mm)/piece_width;
    }else{
        if (isLeftRowECG){
            number_for_pieceviews = ((NSUInteger)self.frame.size.width)/piece_width;
        }else{
            //后移 2.5毫米，如果这个列不是第一列，并且无定标的情况下
            number_for_pieceviews = ((NSUInteger)self.frame.size.width - 2.5 * pix_per_mm)/piece_width;
        }
    }
    
    for (NSPieceView *view in views_array){
        rect = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, self.frame.size.height);
        #if TARGET_OS_IOS
            [view setFrame:rect];
        #else
            [view setFrame:NSRectFromCGRect(rect)];
        #endif
    }


    rect = CGRectMake(0.f, 0.f, 5 * pix_per_mm, self.frame.size.height);
    #if TARGET_OS_IOS
        [standard_view setFrame:rect];
    #else
        [standard_view setFrame:NSRectFromCGRect(rect)];
    #endif


    while (views_array.count < number_for_pieceviews){
        float x_seek = 0.f;
        if (needStandardView){
            x_seek = standard_view.frame.size.width;
        }else{
            if (isLeftRowECG){
                x_seek = 0.f;
            }else{
                //后移 2.5毫米，如果这个列不是第一列，并且无定标的情况下
                x_seek += 2.5 * pix_per_mm;
            }
        }
        rect = CGRectMake(x_seek + views_array.count * piece_width,
                            0.f, piece_width, self.frame.size.height);
        #if TARGET_OS_IOS
            NSPieceView * view = [[NSPieceView alloc] initWithFrame:rect];
        #else
            NSPieceView * view = [[NSPieceView alloc] initWithFrame:NSRectFromCGRect(rect)];
        #endif
        view.index = views_array.count;
        view.dataSource = self;
        view.ecg_name = self.ecg_name_array;
        view.x_seek_per_point = x_seek_per_point;
        view.line_color = line_color;
        view.lost_line_color = lost_line_color;
        view.line_width = line_width;
        view.x_start_init_value = - number_for_more_point_side * x_seek_per_point;
        [views_array addObject:view];
        [self addSubview:view];
    }

    while (views_array.count > number_for_pieceviews) {
        [views_array removeLastObject];
    }
    view_size = self.frame.size;
    current_pieceview_index = 0;
    for (NSPieceView *view in views_array){
        [view clean_in_thread];
    }
}

-(void)init_values_array{
    if (0 == self.frame.size.width){
        return;
    }
    self_width = self.frame.size.width;
    
    pthread_mutex_lock(&data_mutex);
    piece_width = pix_per_mm * x_speed / view_fresh;
    erase_before_index = space_pix / piece_width;
    x_seek_per_point = piece_width * view_fresh / ECG_rate;
    received_values_times = 0;
    showed_values_times = 0;
    current_values_array_index = 0;
    current_pieceview_index = 0;
    if (nil == standard_view){
        standard_view = [[NSECGStandardView alloc] init];
        standard_view.line_width = line_width;
        standard_view.line_color = line_color;
        standard_view.standard_text_color = standard_text_color;
        standard_view.standard_text_font = standard_text_font;
        standard_view.pix_per_mm = pix_per_mm;
        standard_view.y_rate = y_rate;
        standard_view.ecg_name_array = ecg_name_array;
        standard_view.standard_style = standard_style;
        standard_view.style = style;
        [self addSubview:standard_view];
    }
    number_for_pieceviews = ((NSUInteger)self.frame.size.width - 5 * pix_per_mm)/piece_width;
    values_array = [[NSMutableArray alloc] init];
    int number_for_values = number_for_pieceviews * piece_width / x_seek_per_point;
    for (int i=0;i<number_for_values;i++){
        [values_array addObject:[NSNumber numberWithInt:NO_ECG_LINE_VALUE]];
    }
    need_points_per_pieceview = piece_width/x_seek_per_point;
    if (views_array){
        for (NSPieceView *view in views_array){
            [view removeFromSuperview];
        }
        [views_array removeAllObjects];
    }
    views_array = [[NSMutableArray alloc] init];
    [self change_size];
    pthread_mutex_unlock(&data_mutex);
}
    
#if TARGET_OS_IOS
- (void)click_view:(UITapGestureRecognizer *)sender {
    if (delegate){
//        NSLog(@"%f %f", [sender locationInView:self].x,  [sender locationInView:self].y);
        float height = self.frame.size.height/self.ecg_name_array.count;
        float click_y = [sender locationInView:self].y;
        float nn = click_y/height;
        NSString *name = [ecg_name_array objectAtIndex:(NSUInteger)nn];
        [delegate clickedLead:name];
    }
    return;
}
#endif
    
    
-(void)init_all_default{
    int ret = pthread_mutex_init(&data_mutex, nil);
    if (0 != ret){
        NSLog(@"*** Warning  the mutex can NOT init. ***");
    }
#if TARGET_OS_IOS
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click_view:)];
    tap.numberOfTapsRequired = 1;
    tap.numberOfTouchesRequired = 1;
    [self addGestureRecognizer:tap];
#endif
    x_speed = 25.f;
    y_rate = 10.f;
    view_fresh = 25.f;
    ECG_rate = 660.f;
    pix_per_mm = 5.f;
    space_pix = 30;
    style = NSECGRealTimeView_Style_3x4;
    #if TARGET_OS_IOS
    line_color = [UIColor greenColor];
    #else
    line_color = [NSColor greenColor];
    #endif
    line_width = 1.6f;
    number_for_more_point_side = 10;
    current_pieceview_index = 0;
    current_values_array_index = 0;
    [self init_values_array];
}

-(id)initWithCoder:(NSCoder *)coder{
    self = [super initWithCoder:coder];
    if (self){
        [self init_all_default];
    }
    return self;
}

-(id)init{
    self = [super init];
    if (self){
        #if TARGET_OS_IOS
        self.clipsToBounds = YES;
        #endif
        [self init_all_default];
    }
return self;
}


-(void)setFrame:(CGRect)frame{
    [super setFrame:frame];
    [self init_values_array];
}

#if !TARGET_OS_IOS
-(void)setFrameSize:(NSSize)newSize{
    [super setFrameSize:newSize];
    if (view_size.width != newSize.width || view_size.height != newSize.height){
        [self init_values_array];
    }
    return;
}
#endif
    

@end



